﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.Transactions;
using System.Web;
using System.Web.UI.WebControls;
using System.Xml;
using SalePromotion.Pagination;
using SalePromotion.eBay;
using eBay.Service.Call;
using eBay.Service.Core.Sdk;
using eBay.Service.Core.Soap;
using IsolationLevel = System.Data.IsolationLevel;

namespace SalePromotion.Service
{
    public class SaleDiscountService
    {
        private SaleDiscountEntities Entities;
        public SaleDiscountService()
        {
            Entities = new SaleDiscountEntities();
        }
        public EbayUserToken GetEbayUserToken(string ebayUserId)
        {
            return Entities.EbayUserTokens.FirstOrDefault(token => token.eBayUserId == ebayUserId);

        }

        public Sale GetSale(int id)
        {
            return Entities.Sales.FirstOrDefault(sale => sale.Id == id);

        }

        public int GetSaleCount(SaleDiscountCriteria criteria)
        {
            return Entities.Sales.Count();

        }

        public IEnumerable<Sale> SearchSaleByCondition(PaginationOptions pagination, SaleDiscountCriteria criteria)
        {

            var items = Entities.Sales.Where(sale => true).OrderByDescending(sale => sale.StartDate).Skip(pagination.SkipTo).Take(pagination.ItemsPerPage);
            return items;
        }

        public bool RemoveSaleDiscount(int id)
        {
            var trans = new TransactionScope();
            using (trans)
            {
                try
                {
                    var removedItems = new ItemIDArrayType { ItemID = new StringCollection() };
                    //delete 
                    var saleListingCollection = Entities.SaleListings.Where(listing => listing.SaleId == id);
                    foreach (var saleListing in saleListingCollection)
                    {
                        removedItems.ItemID.Add(saleListing.ItemId);
                        Entities.SaleListings.DeleteObject(saleListing);
                        
                    }

                    

                    var sale = Entities.Sales.FirstOrDefault(s => s.Id == id);
                    Debug.Assert(sale != null, "Sale should not be null.");
                    var promationSaleId = sale.PromotionSaleID;
                    var promationSaleName = sale.SaleName;
                    Entities.Sales.DeleteObject(sale);

                    Entities.SaveChanges();
                    if (promationSaleId.HasValue)
                    {
                        var ebaySession = new eBaySession();
                        //remove them from eBay
                        if (saleListingCollection.Any())
                        {
                            ebaySession.RemovePromotionalSaleListings(
                               promationSaleId.Value, removedItems);
                        }
                        ebaySession.SetPromotionalSale(ModifyActionCodeType.Delete, new PromotionalSaleType()
                        {
                            PromotionalSaleID = promationSaleId.Value,
                            PromotionalSaleName = promationSaleName
                        });
                    }
                    trans.Complete();

                }
                catch (Exception)
                {

                    throw;
                }
                return true;
            }


        }
        public EbayUserToken ActivateUser(ApiContext context, string sessionId, string ebayUserName)
        {
            var token = String.Empty;
            var transaction = new TransactionScope();
            using (transaction)
            {
                try
                {
                    context.ApiCredential.eBayAccount = null;
                    var fetchTokenCall = new FetchTokenCall(context);
                    token = fetchTokenCall.FetchToken(sessionId);

                    var ebayUserToken = GetEbayUserToken(ebayUserName);

                    if (ebayUserToken == null)
                    {
                        ebayUserToken = new EbayUserToken();
                        ebayUserToken.Token = String.Empty;
                        Entities.EbayUserTokens.AddObject(ebayUserToken);
                    }

                    if (!String.IsNullOrEmpty(token))
                    {
                        context.ApiCredential.eBayToken = token;

                        ebayUserToken.Token = token;
                        ebayUserToken.eBayUserId = ebayUserName;
                        ebayUserToken.CreatedDate = ebayUserToken.UpdatedDate = DateTime.Now;
                        //get token status
                        var getTokenStatusCall = new GetTokenStatusCall(context);
                        TokenStatusType tokenStatus = getTokenStatusCall.GetTokenStatus();
                        if (tokenStatus.Status == TokenStatusCodeType.Active)
                            ebayUserToken.IsActive = true;
                        else
                            ebayUserToken.IsActive = false;
                        ebayUserToken.TokenExpirationDate = tokenStatus.ExpirationTime;

                    }

                    Entities.SaveChanges();
                    transaction.Complete();
                    return ebayUserToken;
                }
                catch (Exception)
                {
                    ;
                    throw;
                }
            }
        }


        public IEnumerable<ItemInfo> LoadActiveListings(ItemInfoCriteria criteria, bool isGettingSellerList = true)
        {
            var items = isGettingSellerList ? new eBaySession().CallGetSellerList(DateTime.Now, DateTime.Now.AddDays(30)) : new eBaySession().GetActiveListings(GetListingTypeCodeType(criteria), GetItemSortTypeCodeType(criteria));
            foreach (ItemType item in items)
            {
                var itemInfo = new ItemInfo();
                itemInfo.ItemId = item.ItemID;
                itemInfo.PicitureURL = item.PictureDetails.GalleryURL;
                itemInfo.Title = item.Title;
                itemInfo.Qty = item.Quantity;
                itemInfo.ItemFormat = item.ListingType.ToString();
                itemInfo.EndDate = GetEndDate(item);
                itemInfo.ShippingCost = GetShippingCost(item.ShippingDetails);
                itemInfo.CurrentPrice = item.SellingStatus.CurrentPrice.currencyID.ToString() + " $" + item.SellingStatus.CurrentPrice.Value;
                yield return itemInfo;
            }
        }

        public IEnumerable<SaleListing>  GetSaleListings(int saleId)
        {
            return Entities.SaleListings.Where(saleListing => saleListing.SaleId == saleId);
        }
        public void CreateOrUpdateSale(Sale entity, string selectedListings)
        {
            var transaction = new TransactionScope();

            try
            {
                using (transaction)
                {
                    if (entity.Id <= 0)
                    {
                        Entities.Sales.AddObject(entity);
                    }
                    SaveSaleListing(entity, selectedListings);
                    Entities.SaveChanges();
                    CreateSale(entity);
                    transaction.Complete();
                }
               
            }
            catch (Exception)
            {
                ;
                throw;
            }

        }

        private ItemIDArrayType newItemArray;
        private ItemIDArrayType removedItemArray;

        private void SaveSaleListing(Sale entity, string selectedListings)
        {
            newItemArray = (GetItemArray(selectedListings));
            removedItemArray = new ItemIDArrayType();
            removedItemArray.ItemID = new StringCollection();
            var removedSaleListings = new List<SaleListing>();
            if (entity.Id > 0)
            {
                var saleListings = entity.SaleListings;
                foreach (var saleListing in saleListings)
                {
                    if (!newItemArray.ItemID.Contains(saleListing.ItemId))//removed
                    {
                        removedItemArray.ItemID.Add(saleListing.ItemId);
                        removedSaleListings.Add(saleListing);

                    }
                    else
                    {
                        newItemArray.ItemID.Remove(saleListing.ItemId); //still exists ,removed from newItemArray
                    }
                }

                foreach (var item in removedSaleListings)
                {
                    Entities.SaleListings.DeleteObject(item);
                }

            }
            foreach (string item in newItemArray.ItemID)
            {
                var newSaleListing = new SaleListing();
                newSaleListing.ItemId = item;
                newSaleListing.SaleId = entity.Id;
                Entities.SaleListings.AddObject(newSaleListing);

            }


        }
        private ItemIDArrayType GetItemArray(string selectedListings)
        {
            var items = new ItemIDArrayType();
            items.ItemID = new StringCollection();
            if (!string.IsNullOrWhiteSpace(selectedListings))
            {
                items.ItemID.AddRange(selectedListings.Split(new char[] { ',' }));
            }
            return items;
        }

        private void CreateSale(Sale entity)
        {
            var session = new eBaySession();
            var promationSale = new PromotionalSaleType();
            promationSale.PromotionalSaleName = entity.SaleName;
            promationSale.PromotionalSaleStartTime = entity.StartDate;
            promationSale.PromotionalSaleEndTime = entity.EndDate;
            promationSale.DiscountType = entity.DiscountType == (int)DiscountCodeType.Percentage
                ? DiscountCodeType.Percentage
                : DiscountCodeType.Price;
            promationSale.DiscountValue = Convert.ToDouble(entity.DiscountRatio);
            if (entity.IsAuctionExcluded && entity.IsFreeShipping)
            {
                promationSale.PromotionalSaleType1 = PromotionalSaleTypeCodeType.PriceDiscountAndFreeShipping;
            }
            else if (entity.IsFreeShipping)
            {
                promationSale.PromotionalSaleType1 = PromotionalSaleTypeCodeType.FreeShippingOnly;
            }
            else if (entity.IsAuctionExcluded)
            {
                promationSale.PromotionalSaleType1 = PromotionalSaleTypeCodeType.PriceDiscountOnly;
            }
            PromotionalSaleStatusCodeType result = PromotionalSaleStatusCodeType.Active;

            //promotionId
            if (entity.PromotionSaleID.HasValue)
            {
                promationSale.PromotionalSaleID = entity.PromotionSaleID.Value;
                result = session.SetPromotionalSale(ModifyActionCodeType.Update, promationSale);
            }
            else
            {
                result = session.SetPromotionalSale(ModifyActionCodeType.Add, promationSale);
                //update listings
                entity.PromotionSaleID = promationSale.PromotionalSaleID;
      
            }

            entity.Status = result.ToString();
            Entities.SaveChanges();

      
            session.SetPromotionalSaleListings(
                entity.PromotionSaleID.Value,  ModifyActionCodeType.Add, newItemArray,
               entity.StoreCatetoryID ?? 0, 0, entity.AllFixedPriceItems,
                entity.AllStoreInventoryItems, entity.AllAuctionItems);

            if (removedItemArray.ItemID.Count > 0)
            {
                session.RemovePromotionalSaleListings(
                   entity.PromotionSaleID.Value, removedItemArray);
            }



        }
        private DateTime GetEndDate(ItemType item)
        {
            ;
            return DateTime.Now.Add(XmlConvert.ToTimeSpan(item.TimeLeft));
        }
        private ItemSortTypeCodeType GetItemSortTypeCodeType(ItemInfoCriteria criteria)
        {
            return (ItemSortTypeCodeType)Enum.Parse(typeof(ItemSortTypeCodeType), criteria.SortBy);
        }


        private ListingTypeCodeType GetListingTypeCodeType(ItemInfoCriteria criteria)
        {
            return (ListingTypeCodeType)Enum.Parse(typeof(ListingTypeCodeType), criteria.ItemFormat);
        }

        private string GetShippingCost(ShippingDetailsType shippingDetails)
        {
            if (shippingDetails.ShippingServiceOptions.Count > 0)
            {
                var firstShippingServiceOptions = shippingDetails.ShippingServiceOptions[0];
                if (firstShippingServiceOptions.FreeShipping)
                    return "Free";
                var shippingCost = String.Empty;
                if (firstShippingServiceOptions.ShippingServiceCost != null)
                {
                    shippingCost += GetCurrencyString(firstShippingServiceOptions.ShippingServiceCost);
                }
                if (firstShippingServiceOptions.ShippingInsuranceCost != null)
                {
                    shippingCost += "<Br/>";
                    shippingCost += GetCurrencyString(firstShippingServiceOptions.ShippingInsuranceCost);
                }
                return shippingCost;
            }
            return String.Empty;
        }

        private string GetCurrencyString(AmountType amountType)
        {
            return amountType.currencyID.ToString() + " $" + amountType.Value;
        }



    }

    [Serializable]
    public class SaleDiscountCriteria
    {
        public string Name { get; set; }
        public FilterBy Filter { get; set; }
    }


    [Serializable]
    public class ItemInfoCriteria
    {

        public string keyword { get; set; }

        public string ItemFormat { get; set; }
        [DataMember]
        public string StoreCategoryId { get; set; }
        [DataMember]
        public string SortBy { get; set; }

    }


    public class ItemInfo
    {

        public string ItemId { get; set; }

        public string PicitureURL { get; set; }

        public string Title { get; set; }

        public string CurrentPrice { get; set; }

        public int Qty { get; set; }

        public string ShippingCost { get; set; }

        public string ItemFormat { get; set; }

        public DateTime EndDate { get; set; }
    }

    public enum FilterBy
    {
        All,
        Active,
        Scheduled,
        Inactive
    }

}